home *** CD-ROM | disk | FTP | other *** search
- /* #Specification: html mode / access limitation
- We can specify the network or host which are allowed to access linuxconf
- in web mode. We can simply define a set of network and netmask pairs.
- */
- #include <stdio.h>
- #include <string.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include "../misc/misc.h"
- #include "../dialog/dialog.h"
- #include "internal.h"
- #include "netconf.h"
- #include "netconf.m"
-
- static NETCONF_HELP_FILE help_access ("html_access");
-
- class HTML_ACCESS: public ARRAY_OBJ{
- public:
- SSTRING net;
- SSTRING mask;
- unsigned long badr;
- unsigned long bmask;
- int err; // Is this entry is valid (usable)
- /*~PROTOBEG~ HTML_ACCESS */
- public:
- HTML_ACCESS (const char *_net, const char *_mask);
- /*~PROTOEND~ HTML_ACCESS */
- };
-
- PUBLIC HTML_ACCESS::HTML_ACCESS(const char *_net, const char *_mask)
- {
- net.setfrom (_net);
- mask.setfrom (_mask);
- err = 0;
- badr = bmask = 0;
- }
-
- class HTML_ACCESS_TB: public ARRAY{
- /*~PROTOBEG~ HTML_ACCESS_TB */
- public:
- HTML_ACCESS_TB (void);
- private:
- void addfield (DIALOG&dia, HTML_ACCESS *a);
- void addfields (DIALOG&dia);
- public:
- int check (unsigned long badr);
- int compute (char *errmsg);
- void edit (void);
- HTML_ACCESS *getitem (int no);
- void setdefaults (void);
- void write (void);
- /*~PROTOEND~ HTML_ACCESS_TB */
- };
-
- static const char HTMLACCESS[]="htmlaccess";
- static const char FROM[]="from";
-
- PUBLIC HTML_ACCESS_TB::HTML_ACCESS_TB()
- {
- SSTRINGS tb;
- int n = linuxconf_getall (HTMLACCESS,FROM,tb,0);
- for (int i=0; i<n; i++){
- SSTRING *s = tb.getitem(i);
- char net[200];
- char mask[200];
- mask[0] = '\0';
- sscanf (s->get(),"%s %s",net,mask);
- add (new HTML_ACCESS(net,mask));
- }
- }
-
- PUBLIC HTML_ACCESS *HTML_ACCESS_TB::getitem(int no)
- {
- return (HTML_ACCESS *)ARRAY::getitem(no);
- }
-
- PUBLIC void HTML_ACCESS_TB::write()
- {
- int n=getnb();
- linuxconf_removeall(HTMLACCESS,FROM);
- for (int i=0; i<n; i++){
- HTML_ACCESS *a = getitem(i);
- if (!a->net.is_empty()){
- char buf[400];
- sprintf (buf,"%s %s",a->net.get(),a->mask.get());
- linuxconf_add (HTMLACCESS,FROM,buf);
- }
- }
- linuxconf_save();
- }
-
- /*
- Add one network to the dialog
- */
- PRIVATE void HTML_ACCESS_TB::addfield(DIALOG &dia, HTML_ACCESS *a)
- {
- dia.newf_str (MSG_U(F_NETWORKHOST,"network or host"),a->net);
- dia.newf_str (MSG_U(F_NETMASKOPT,"netmask(opt)"),a->mask);
- }
-
- /*
- Add two empty networks to the dialog
- */
- PRIVATE void HTML_ACCESS_TB::addfields(DIALOG &dia)
- {
- for (int i=0; i<2; i++){
- HTML_ACCESS *a = new HTML_ACCESS ("","");
- add (a);
- addfield (dia,a);
- }
- }
- static HTML_ACCESS_TB *lookup; // Use to speed up html_access_check
- // avoiding reloading the struct all
- // the time.
-
- PUBLIC void HTML_ACCESS_TB::edit()
- {
- DIALOG dia;
- /* #Specification: html access / dialog / add button
- The add button simply add few more empty lines at the
- end of the dialog
- */
- int n=getnb();
- for (int i=0; i<n; i++){
- HTML_ACCESS *a = getitem(i);
- addfield (dia,a);
- }
- addfields(dia);
- dia.addwhat (MSG_U(F_EMPTYSLOT,"empty slots at the end of the dialog"));
- int nof = 0;
- while (1){
- MENU_STATUS code = dia.edit (
- MSG_U(T_HTMLACCESS,"Linuxconf html access control")
- ,MSG_U(I_HTMLACCESS
- ,"You can specify which networks or hosts are allowed\n"
- "to access linuxconf to configure your computer\n"
- "(They need a password still)\n")
- ,help_access
- ,nof
- ,MENUBUT_CANCEL|MENUBUT_ACCEPT|MENUBUT_ADD);
- char errmsg[10000];
- if (code == MENU_CANCEL || code == MENU_ESCAPE){
- break;
- }else if (code == MENU_ADD){
- addfields(dia);
- }else if (compute(errmsg)==-1){
- xconf_error ("%s",errmsg);
- }else{
- delete lookup;
- lookup = NULL;
- write();
- break;
- }
- }
- }
-
- void html_access_edit()
- {
- HTML_ACCESS_TB htb;
- htb.edit ();
- }
-
- /*
- To speed up peer lookup, we walk the list of hosts/networks allowed
- and resolved the addresses and netmask
-
- This function is also used to validate the dialog inputs.
-
- Return -1 if any error in the data.
- */
- PUBLIC int HTML_ACCESS_TB::compute(char *errmsg)
- {
- errmsg[0] = '\0';
- int ret = 0;
- int n = getnb();
- for (int i=0; i<n; i++){
- HTML_ACCESS *a = getitem(i);
- a->err = 0;
- const char *net = a->net.get();
- if (net[0] != '\0'){
- /* #Specification: html access / host or net spec
- We can use the following things to specify a network or
- host access. A default suitable netmask is computed
- and is used unless one is supplied in the dialog.
-
- #
- -An IP number
- -A host name
- -A network name
- -A device name (eth0). In this case the spec will be
- extracted
- #
- */
- char ipstr[16],mskstr[16];
- if (ipfwrule_convert (net,ipstr,mskstr)==-1){
- ret = -1;
- a->err = 1;
- errmsg += sprintf (errmsg
- ,MSG_U(E_IVLDHOSTNET,"invalid host or network: %s\n")
- ,net);
- }else{
- int n[4];
- device_aip24(ipstr,n);
- a->badr = (n[0] << 24) + (n[1] << 16) + (n[2] << 8) + n[3];
- const char *msk = a->mask.get();
- if (msk[0] == '\0') msk = mskstr;
- if (device_aip24(msk,n)!=-1){
- a->bmask = (n[0] << 24) + (n[1] << 16) + (n[2] << 8) + n[3];
- }else{
- ret = -1;
- a->err = 1;
- errmsg += sprintf (errmsg
- ,MSG_U(E_IVLDMASK,"invalid netmask: %s\n")
- ,msk);
- }
- }
- /* #Specification: html access / using a host to spec a net
- One can use a host to specify a network by using the
- proper netmask. This allows one to say "I accept all
- machine of the same network as this one".
- */
- a->badr &= a->bmask;
- }
- }
- return ret;
- }
-
- /*
- Tell if one host address is acceptable (in this list)
- Return -1 if not
- */
- PUBLIC int HTML_ACCESS_TB::check(unsigned long badr)
- {
- int ret = -1;
- int n = getnb();
- for (int i=0; i<n; i++){
- HTML_ACCESS *a = getitem(i);
- if (!a->err){
- if (a->badr==(badr & a->bmask)){
- ret = 0;
- }
- }
- }
- return ret;
- }
-
- /*
- Record default rules when noone are defined
- See the spec at the top of this file
- */
- PUBLIC void HTML_ACCESS_TB::setdefaults()
- {
- /* #Specification: html mode / access limitation / default rule
- The default behavior is to accept connection originating from
- the eth0 network only and the localhost.
-
- Once one rule is entered, the default is gone, even the loopback won't
- be accepted.
- */
- if (getnb()==0){
- // Set the default behavior
- add (new HTML_ACCESS("127.0.0.1","255.255.255.255"));
- HOSTINFO info;
- if (netconf_loadinfos(info)!=-1){
- const char *ipadr = info.a[0].ipaddr.get();
- char stdmask[16];
- const char *mask = info.a[0].netmask.get();
- if (mask[0] == '\0'){
- mask = stdmask;
- char stdnet[16];
- device_setstdnetmask(ipadr,stdnet,stdmask);
- }
- add (new HTML_ACCESS(ipadr,mask));
- }
- }
- }
- /*
- Check if a socket connection is coming from an accepted host
- Return 0 if the "client" is allowed, -1 if not.
- */
- int html_access_check (int fd)
- {
- int ret = -1;
- struct sockaddr_in adr;
- int len = sizeof(adr);
- if (getpeername (fd,(struct sockaddr*)&adr,&len) != -1){
- if (lookup == NULL){
- lookup = new HTML_ACCESS_TB;
- lookup->setdefaults();
- char errmsg[10000];
- lookup->compute(errmsg);
- }
- ret = lookup->check(ntohl(adr.sin_addr.s_addr));
- }
- return ret;
- }
-